package com.mlink.ai.chat.ui.viewmodel

import android.content.Context
import android.os.Build
import androidx.lifecycle.ViewModel
import com.cipher.CipherUtils
import com.google.gson.Gson
import com.google.gson.annotations.SerializedName
import com.mlink.ai.chat.AiChatApplication
import com.mlink.ai.chat.assistant.robot.BuildConfig
import com.mlink.ai.chat.network.Api
import com.mlink.ai.chat.network.bean.ApiResponse
import com.mlink.ai.chat.utils.DeviceUtils
import com.mlink.ai.chat.utils.SingleLiveEvent
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody
import org.json.JSONObject
import java.io.File

class FeedbackViewModel : ViewModel() {

    val isSuccess = SingleLiveEvent<Boolean>()

    fun feedbackWithFile(
        context: Context,
        categoryList: List<String>,
        detail: String,
        fileList: List<File>,
        email: String
    ) {
        GlobalScope.launch(Dispatchers.IO) {
            runCatching {
                val uid = DeviceUtils.getUid()
                val packageName = context.packageName
                val source = "${uid}033e1e8632bda3e2${packageName}"
                val md5 = CipherUtils.getMD5(source.toByteArray())
                val map = hashMapOf<String, Any>().apply {
                    put("uid", uid)
                    put("signature", md5)
                    put("pkg", packageName)
                }
                Api.chatApi.getFeedbackToken("https://fs.cocomobi.com/api/v1/token", map)
            }.onSuccess {
                if (it.ret == 200) {
                    val json = Gson().toJson(it.data)
                    val jsonObject = JSONObject(json)
                    val token = jsonObject.getString("token")
                    uploadFile(context, categoryList, detail, fileList, email, token)
                    return@onSuccess
                }
                isSuccess.postValue(false)

            }.onFailure {
                isSuccess.postValue(false)
            }
        }
    }

    private suspend fun uploadFile(
        context: Context,
        categoryList: List<String>,
        detail: String,
        fileList: List<File>,
        email: String,
        token: String
    ) {
        GlobalScope.launch(Dispatchers.IO) {
            val source = "${token}Emoji_JingNCK567"
            val md5 = CipherUtils.getMD5(source.toByteArray())
            val map = hashMapOf<String, RequestBody>()
            map["token"] = RequestBody.create("text/plain".toMediaTypeOrNull(), token)
            map["md5"] = RequestBody.create("text/plain".toMediaTypeOrNull(), md5)
            val deferredList = mutableListOf<Deferred<ApiResponse<Any>>>()
            fileList.forEach { file ->
                val fileRQ = RequestBody.create("image/*".toMediaTypeOrNull(), file)
                val part = MultipartBody.Part.createFormData("file", file.name, fileRQ)
                val deferred = async {
                    Api.chatApi.uploadFile(
                        "https://fs.cocomobi.com/api/v1/uploadFeedBackFile",
                        map,
                        part
                    )
                }
                deferredList.add(deferred)
            }

            val urlList = mutableListOf<String>()
            deferredList.forEach { deferred ->
                runCatching {
                    val response = deferred.await()
                    if (response.ret == 200) {
                        val json = Gson().toJson(response.data)
                        val jsonObject = JSONObject(json)
                        val url = jsonObject.getString("url")
                        urlList.add(url)
                    }
                }
            }

            feedback(context, categoryList, detail, email, urlList)
        }
    }

    fun feedback(
        context: Context,
        categoryList: List<String>,
        detail: String,
        email: String,
        urlList: List<String>
    ) {
        val time = System.currentTimeMillis()
        val source = "${time}Emoji_JingNCK567"
        val md5 = CipherUtils.getMD5(source.toByteArray())
        val builder = StringBuilder()
        urlList.forEach {
            builder.append("$it;")
        }
        var urls = builder.toString()
        if (urls.isNotEmpty()) {
            urls = urls.substring(0, urls.length - 1)
        }
        GlobalScope.launch(Dispatchers.IO) {
            runCatching {
                val content = Content("1", arrayOf(detail))
                val option = Option("1", categoryList.toTypedArray())
                val request = FeedbackRequest(
                    if (AiChatApplication.app.appViewModel.isSubscribed()) 1 else 0,
                    Build.MODEL,
                    context.packageName,
                    md5,
                    time,
                    DeviceUtils.getUid(),
                    Build.VERSION.RELEASE,
                    BuildConfig.VERSION_NAME,
                    email,
                    arrayOf(option),
                    arrayOf(content),
                    urls
                )
                Api.chatApi.feedback("https://feedback.cocomobi.com/api/v2/feedbackinsert", request)
            }.onSuccess {
                if (it.ret == 200) {
                    isSuccess.postValue(true)
                    return@onSuccess
                }
                isSuccess.postValue(false)
            }.onFailure {
                isSuccess.postValue(false)
            }
        }
    }
}

data class FeedbackRequest(
    @SerializedName("subscribe")
    val subscribe: Int,
    @SerializedName("device")
    val device: String,
    @SerializedName("package")
    val packageName: String,
    @SerializedName("signature")
    val signature: String,
    @SerializedName("time")
    val time: Long,
    @SerializedName("uid")
    val uid: String,
    @SerializedName("sysversion")
    val sysversion: String,
    @SerializedName("appversion")
    val appversion: String,
    @SerializedName("email")
    val email: String,
    @SerializedName("option")
    val option: Array<Option>,
    @SerializedName("content")
    val content: Array<Content>,
    @SerializedName("url")
    val url: String
)

data class Option(
    @SerializedName("title")
    val title: String,
    @SerializedName("answer")
    val answer: Array<String>
)

data class Content(
    @SerializedName("title")
    val title: String,
    @SerializedName("answer")
    val answer: Array<String>
)
